﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace Gmantis.Controls.DataGrid
{
    internal interface IDataGridViewItem
    {
        // Methods
        void FinalizeViewItem();
        void InitializeViewItem();

        // Properties
        int Index { get; }
    }

    internal class ViewRow : IDataGridViewItem
    {
        // Fields
        private Dictionary<ViewColumn, DataGridCellPresenter> _cellPresenters = new Dictionary<ViewColumn, DataGridCellPresenter>();
        private double? _desiredHeight = 0.0;
        private double? _detailsDesiredHeight = 0.0;
        private DataGridDetailsPresenter _detailsPresenter;
        private DataGridRowHeaderPresenter _headerPresenter;
        public double _offset;
        private DataGridRowPresenter _presenter;
        public double DetailsOffset;

        // Methods
        public ViewRow(DataGridView view, DataGridRow row)
        {
            this.View = view;
            this.Row = row;
            this.MaxHeightColumnDisplayIndex = -1;
        }

        internal static void ApplyCellStyle(DataGridCellPresenter cellPresenter, DataGridRow row, DataGridColumn column)
        {
            Style cellPresenterStyle = row.GetCellPresenterStyle(column);
            if (cellPresenterStyle != null)
            {
                cellPresenter.Style = cellPresenterStyle;
            }
        }

        private static void ApplyRowHeaderStyle(DataGridRowHeaderPresenter rowHeader, DataGridRow row)
        {
            Style rowHeaderPresenterStyle = row.GetRowHeaderPresenterStyle();
            if (rowHeaderPresenterStyle != null)
            {
                rowHeader.Style = rowHeaderPresenterStyle;
            }
        }

        private static void ApplyRowStyle(DataGridRowPresenter rowPresenter, ViewRow viewRow)
        {
            Style rowPresenterStyle = viewRow.Row.GetRowPresenterStyle();
            if (rowPresenterStyle != null)
            {
                rowPresenter.Style = rowPresenterStyle;
            }
        }

        public void AutoSize()
        {
            this.ClearCachedData();
            this.Row.Height = DataGridLength.Auto;
            this.View.InvalidatePanelsMeasure();
            this.View.OnRowResized(this.Row, this.Row.ViewRow.DesiredHeight);
        }

        public void ClearCachedData()
        {
            this.MaxHeightColumnDisplayIndex = -1;
            this._desiredHeight = null;
            this._detailsDesiredHeight = null;
        }

        private DataGridCellPresenter CreateCellPresenter(ViewColumn viewColumn)
        {
            DataGridCellPresenter cellPresenter = this.Row.CreateCellPresenter(viewColumn.Column);
            if (cellPresenter == null)
            {
                throw new Exception("The method GetCellPresenter(column) of DataGridRow must return a cell if the method HasCellPresenter(column) regarding the same column returned true.");
            }
            DataGrid dataGrid = viewColumn.Column.DataGrid;
            ApplyCellStyle(cellPresenter, this.Row, viewColumn.Column);
            cellPresenter.SetBinding<DataGrid>(DataGridCellPresenter.FocusStyleProperty, dataGrid, dg => dg.FocusStyle);
            cellPresenter.SetBinding<DataGrid>(DataGridCellPresenter.SelectedBackgroundProperty, dataGrid, dg => dg.SelectedBackground);
            cellPresenter.SetBinding<DataGrid>(DataGridCellPresenter.PressedBrushProperty, dataGrid, dg => dg.PressedBrush);
            cellPresenter.SetBinding<DataGrid>(DataGridCellPresenter.MouseOverBrushProperty, dataGrid, dg => dg.MouseOverBrush);
            cellPresenter.SetBinding<DataGrid>(DataGridCellPresenter.ValidationBackgroundProperty, dataGrid, dg => dg.ValidationBackground);
            return cellPresenter;
        }

        private DataGridDetailsPresenter CreateDetailsPresenter()
        {
            DataGridDetailsPresenter target = new DataGridDetailsPresenter();
            target.SetBinding<DataGrid>(DataGridDetailsPresenter.HorizontalGridLineBrushProperty, this.DataGrid, dg => dg.HorizontalGridLinesBrush);
            target.SetBinding<DataGrid>(DataGridDetailsPresenter.HorizontalGridLineVisibilityProperty, this.DataGrid, dg => dg.GridLinesVisibility, CustomConverter.Create((value, type, parameter, culture) => ((((DataGridGridLinesVisibility)value) & DataGridGridLinesVisibility.Horizontal) == DataGridGridLinesVisibility.Horizontal) ? Visibility.Visible : Visibility.Collapsed));
            return target;
        }

        private DataGridRowHeaderPresenter CreateRowHeaderPresenter()
        {
            DataGridRowHeaderPresenter rowHeader = this.Row.CreateRowHeaderPresenter();
            ApplyRowHeaderStyle(rowHeader, this.Row);
            rowHeader.SetBinding<DataGrid>(Control.BackgroundProperty, this.DataGrid, dg => dg.HeaderBackground);
            rowHeader.SetBinding<DataGrid>(Control.ForegroundProperty, this.DataGrid, dg => dg.HeaderForeground);
            rowHeader.SetBinding<DataGrid>(Control.BorderBrushProperty, this.DataGrid, dg => dg.BorderBrush);
            rowHeader.SetBinding<DataGrid>(DataGridRowHeaderPresenter.SelectedBackgroundProperty, this.DataGrid, dg => dg.SelectedBackground);
            rowHeader.SetBinding<DataGrid>(DataGridRowHeaderPresenter.PressedBrushProperty, this.DataGrid, dg => dg.PressedBrush);
            rowHeader.SetBinding<DataGrid>(DataGridRowHeaderPresenter.MouseOverBrushProperty, this.DataGrid, dg => dg.MouseOverBrush);
            rowHeader.SetBinding<DataGrid>(DataGridRowHeaderPresenter.ValidationBackgroundProperty, this.DataGrid, dg => dg.ValidationBackground);
            rowHeader.SetBinding<DataGrid>(DataGridRowHeaderPresenter.ValidationForegroundProperty, this.DataGrid, dg => dg.ValidationForeground);
            return rowHeader;
        }

        private DataGridRowPresenter CreateRowPresenter()
        {
            DataGridRowPresenter rowPresenter = this.Row.CreateRowPresenter();
            ApplyRowStyle(rowPresenter, this);
            rowPresenter.SetBinding<DataGrid>(Control.BorderBrushProperty, this.DataGrid, dg => dg.BorderBrush);
            rowPresenter.SetBinding<DataGrid>(DataGridRowPresenter.ValidationBackgroundProperty, this.DataGrid, dg => dg.ValidationBackground);
            if (rowPresenter is DataGridSelectableRowPresenter)
            {
                rowPresenter.SetBinding<DataGrid>(DataGridSelectableRowPresenter.SelectedBackgroundProperty, this.DataGrid, dg => dg.SelectedBackground);
                rowPresenter.SetBinding<DataGrid>(DataGridSelectableRowPresenter.PressedBrushProperty, this.DataGrid, dg => dg.PressedBrush);
                rowPresenter.SetBinding<DataGrid>(DataGridSelectableRowPresenter.MouseOverBrushProperty, this.DataGrid, dg => dg.MouseOverBrush);
            }
            rowPresenter.SetBinding(DataGridRowPresenter.CellsAreaMarginProperty, new Binding().From<DataGridViewProperties>(this.View.Properties, x => x.CellsAreaMargin));
            return rowPresenter;
        }

        internal void FinalizeCellPresenter(ViewColumn viewColumn)
        {
            DataGridCellPresenter presenter;
            if (this._cellPresenters.TryGetValue(viewColumn, out presenter) && !presenter.IsLoading)
            {
                this.DataGrid.OnUnloadedCellPresenter(new DataGridCellEventArgs(presenter.Cell));
                presenter.Unload();
                this.Row.UnbindCellContent(presenter.CellContent, viewColumn.Column);
                presenter.MergedRange = null;
                this._cellPresenters.Remove(viewColumn);
                this._presenter.CellsPanel.RemoveChild(presenter);
                presenter.ViewRow = null;
                presenter.ViewColumn = null;
            }
        }

        private void FinalizeCellsPresenters()
        {
            if ((this._presenter != null) && (this._presenter._elementCells != null))
            {
                this._presenter._elementCells.RemoveChildren();
            }
        }

        private void FinalizeDetailsPresenter(bool removeFromPanel)
        {
            if (this._detailsPresenter != null)
            {
                DataGridDetailsPresenter presenter = this._detailsPresenter;
                this.DataGrid.OnUnloadedRowDetailsPresenter(new DataGridRowDetailsEventArgs(this.Row, presenter.Content as FrameworkElement));
                this._detailsPresenter = null;
                if (removeFromPanel)
                {
                    this.Panel.Children.Remove(presenter);
                }
            }
        }

        internal void FinalizeRowHeaderPresenter()
        {
            if ((this._headerPresenter != null) && !this._headerPresenter.IsLoading)
            {
                DataGridRowHeaderPresenter presenter = this._headerPresenter;
                this.DataGrid.OnUnloadedRowHeaderPresenter(new DataGridRowEventArgs(this.Row));
                presenter.ClearValue(DataGridRowHeaderPresenter.CanUserResizeProperty);
                presenter.ClearValue(DataGridRowHeaderPresenter.CanUserToggleDetailsProperty);
                presenter.ClearValue(DataGridRowHeaderPresenter.DetailsVisibilityProperty);
                presenter.Resized -= new EventHandler<PropertyChangedEventArgs<double>>(this.HeaderPresenter_Resized);
                presenter.Resizing -= new EventHandler<PropertyChangedEventArgs<double>>(this.HeaderPresenter_Resizing);
                presenter.AutoSized -= new EventHandler(this.HeaderPresenter_AutoSized);
                presenter.Unload();
                this._headerPresenter = null;
                this.Row.UnbindRowHeaderPresenter(presenter);
                this.View.RowsHeaderPanel.RemoveChild(presenter);
                presenter.ViewRow = null;
            }
        }

        internal void FinalizeRowPresenter()
        {
            if ((this._presenter != null) && !this._presenter.IsLoading)
            {
                DataGridRowPresenter presenter = this._presenter;
                this.DataGrid.OnUnloadedRowPresenter(new DataGridRowEventArgs(this.Row));
                presenter.Unload();
                presenter.ClearValue(DataGridRowPresenter.HorizontalGridLineOpacityProperty);
                this._presenter = null;
                this.Row.UnbindRowPresenter(presenter);
                this.Panel.RemoveChild(presenter);
                presenter.ViewRow = null;
            }
        }

        public void FinalizeViewItem()
        {
            this.UnloadRow();
        }

        internal DataGridCellPresenter GetCellPresenter(ViewColumn viewColumn, bool forceCreate)
        {
            Func<UIElement> creator = null;
            if (this.Row.HasCellPresenter(viewColumn.Column))
            {
                if (this._cellPresenters.ContainsKey(viewColumn))
                {
                    return this._cellPresenters[viewColumn];
                }
                if (forceCreate)
                {
                    if (creator == null)
                    {
                        creator = () => this.CreateCellPresenter(viewColumn);
                    }
                    DataGridCellPresenter child = (DataGridCellPresenter)this._presenter.CellsPanel.GetChild(this.GetCellPresenterRecyclingKey(viewColumn.Column), creator);
                    this._cellPresenters[viewColumn] = child;
                    this.InitializeCellPresenter(viewColumn, child);
                    return child;
                }
            }
            return null;
        }

        public object GetCellPresenterRecyclingKey(DataGridColumn column)
        {
            object cellPresenterRecyclingKey = this.Row.GetCellPresenterRecyclingKey(column);
            Style cellPresenterStyle = this.Row.GetCellPresenterStyle(column);
            object cellContentRecyclingKey = this.Row.GetCellContentRecyclingKey(column);
            Style cellContentStyle = this.Row.GetCellContentStyle(column);
            if ((cellPresenterRecyclingKey != null) && (cellContentRecyclingKey != null))
            {
                return new CellRecyclingKey(cellPresenterRecyclingKey, cellPresenterStyle, cellContentRecyclingKey, cellContentStyle);
            }
            return null;
        }

        internal DataGridDetailsPresenter GetDetailsPresenter(bool forceCreate)
        {
            if ((this._detailsPresenter == null) && forceCreate)
            {
                this._detailsPresenter = this.CreateDetailsPresenter();
                this.InitializeDetailsPresenter();
            }
            return this._detailsPresenter;
        }

        public DataGridRowHeaderPresenter GetHeaderPresenter()
        {
            return null;
        }

        internal DataGridRowHeaderPresenter GetHeaderPresenter(bool forceCreate)
        {
            Func<UIElement> creator = null;
            if ((this._headerPresenter == null) && forceCreate)
            {
                if (creator == null)
                {
                    creator = () => this.CreateRowHeaderPresenter();
                }
                this._headerPresenter = (DataGridRowHeaderPresenter)this.View.RowsHeaderPanel.GetChild(this.GetRowHeaderPresenterRecyclingKey(), creator);
                this.InitializeRowHeaderPresenter();
            }
            return this._headerPresenter;
        }

        public object GetRowHeaderPresenterRecyclingKey()
        {
            object rowHeaderPresenterRecyclingKey = this.Row.GetRowHeaderPresenterRecyclingKey();
            Style rowHeaderPresenterStyle = this.Row.GetRowHeaderPresenterStyle();
            if (rowHeaderPresenterRecyclingKey == null)
            {
                return null;
            }
            return new TwoMembersRecyclingKey(rowHeaderPresenterRecyclingKey, rowHeaderPresenterStyle);
        }

        public DataGridRowPresenter GetRowPresenter(bool forceCreate)
        {
            Func<UIElement> creator = null;
            if ((this._presenter == null) && forceCreate)
            {
                if (creator == null)
                {
                    creator = () => this.CreateRowPresenter();
                }
                this._presenter = (DataGridRowPresenter)this.Panel.GetChild(this.GetRowPresenterRecyclingKey(), creator);
                this.InitializeRowPresenter();
            }
            return this._presenter;
        }

        public object GetRowPresenterRecyclingKey()
        {
            object rowPresenterRecyclingKey = this.Row.GetRowPresenterRecyclingKey();
            Style rowPresenterStyle = this.Row.GetRowPresenterStyle();
            if (rowPresenterRecyclingKey == null)
            {
                return null;
            }
            return new TwoMembersRecyclingKey(rowPresenterRecyclingKey, rowPresenterStyle);
        }

        internal double GetTotalRenderHeight()
        {
            return (this.RenderHeight + ((this.Row.ActualDetailsVisibility == Visibility.Visible) ? this.DetailsRenderHeight : 0.0));
        }

        internal DataGridVerticalFreezingSeparatorPresenter GetVerticalFreezingSeparatorPresenter()
        {
            return this._presenter.CellsPanel.GetVerticalFreezingSeparatorPresenter(() => this.View.CreateVerticalFreezingSeparatorPresenter());
        }

        private void HeaderPresenter_AutoSized(object sender, EventArgs e)
        {
            this.AutoSize();
        }

        private void HeaderPresenter_Resized(object sender, PropertyChangedEventArgs<double> e)
        {
            this.UpdateHeight(e.NewValue);
            this.View.OnRowResized(this.Row, e.NewValue);
        }

        private void HeaderPresenter_Resizing(object sender, PropertyChangedEventArgs<double> e)
        {
            this.UpdateHeight(e.NewValue);
            this.View.OnRowResizing(this.Row, e.NewValue);
        }

        private void InitializeCellPresenter(ViewColumn viewColumn, DataGridCellPresenter cellPresenter)
        {
            cellPresenter.IsLoading = true;
            cellPresenter.ViewColumn = viewColumn;
            cellPresenter.ViewRow = this;
            if (!cellPresenter.HaveContent)
            {
                cellPresenter.Content = this.Row.CreateCellContent(viewColumn.Column);
            }
            cellPresenter.MergedRange = new DataGridCellsRange(cellPresenter.Cell);
            this.Row.BindCellContent(cellPresenter.CellContent, viewColumn.Column);
            cellPresenter.Load();
            cellPresenter.IsLoading = false;
            this.DataGrid.OnLoadedCellPresenter(new DataGridCellEventArgs(cellPresenter.Cell));
        }

        private void InitializeDetailsPresenter()
        {
            this._detailsPresenter.ViewRow = this;
            FrameworkElement detailsElement = this.View.DataGrid.RowDetailsTemplate.LoadContent() as FrameworkElement;
            this._detailsPresenter.Content = detailsElement;
            this.UpdateRowDetailsBackgroundAndForeground();
            detailsElement.DataContext = this.Row.DataItem;
            this.DataGrid.OnLoadedRowDetailsPresenter(new DataGridRowDetailsEventArgs(this.Row, detailsElement));
        }

        private void InitializeRowHeaderPresenter()
        {
            this._headerPresenter.IsLoading = true;
            this._headerPresenter.ViewRow = this;
            this._headerPresenter.SetBinding(DataGridRowHeaderPresenter.CanUserResizeProperty, new Binding().From<DataGridRow>(this.Row, x => x.CanUserResize));
            this._headerPresenter.SetBinding(DataGridRowHeaderPresenter.CanUserToggleDetailsProperty, new Binding().From<DataGridRow>(this.Row, x => x.ActualCanUserToggleDetails));
            Binding binding = new Binding
            {
                Mode = BindingMode.TwoWay
            };
            this._headerPresenter.SetBinding(DataGridRowHeaderPresenter.DetailsVisibilityProperty, binding.From<DataGridRow>(this.Row, x => x.DetailsVisibility));
            this._headerPresenter.Resized += new EventHandler<PropertyChangedEventArgs<double>>(this.HeaderPresenter_Resized);
            this._headerPresenter.Resizing += new EventHandler<PropertyChangedEventArgs<double>>(this.HeaderPresenter_Resizing);
            this._headerPresenter.AutoSized += new EventHandler(this.HeaderPresenter_AutoSized);
            this.Row.BindRowHeaderPresenter(this._headerPresenter);
            this._headerPresenter.Load();
            this._headerPresenter.IsLoading = false;
            this.DataGrid.OnLoadedRowHeaderPresenter(new DataGridRowEventArgs(this.Row));
        }

        private void InitializeRowPresenter()
        {
            this._presenter.IsLoading = true;
            this._presenter.ViewRow = this;
            this.UpdateRowAreMargin();
            if (this.DataGrid.IsDetailsTogglingAllowed)
            {
                Binding binding = new Binding
                {
                    Converter = CustomConverter.Create((value, type, parameter, culture) => (((Visibility)value) == Visibility.Visible) ? 0 : 1)
                };
                this._presenter.SetBinding(DataGridRowPresenter.HorizontalGridLineOpacityProperty, binding.From<DataGridRow>(this.Row, x => x.ActualDetailsVisibility));
            }
            this.UpdateRowBackgroundAndForeground();
            this._presenter.Load();
            this.Row.BindRowPresenter(this._presenter);
            this._presenter.IsLoading = false;
            this.DataGrid.OnLoadedRowPresenter(new DataGridRowEventArgs(this.Row));
        }

        public void InitializeViewItem()
        {
            this.LoadRow();
        }

        private void LoadRow()
        {
            this.Row.Errors.CollectionChanged += new NotifyCollectionChangedEventHandler(this.OnErrorsCollectionChanged);
        }

        private void OnErrorsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.UpdateValidationState();
        }

        public void RemoveEditingCell(ViewColumn viewColumn)
        {
            if (this._presenter != null)
            {
                this._presenter.EditCompleted(viewColumn);
            }
        }

        internal FrameworkElement SetEditingCell(ViewColumn viewColumn)
        {
            if (this._presenter != null)
            {
                return this._presenter.SetEditingCell(viewColumn);
            }
            return null;
        }

        internal void Unload(bool refreshRow = true, bool refreshCells = true, bool refreshRowHeader = true)
        {
            if (refreshRow)
            {
                this.FinalizeRowPresenter();
                this.FinalizeDetailsPresenter(true);
            }
            else if (refreshCells)
            {
                this.FinalizeCellsPresenters();
            }
            if (refreshRowHeader)
            {
                this.FinalizeRowHeaderPresenter();
            }
            this.ClearCachedData();
            if (this.Panel != null)
            {
                this.Panel.InvalidateMeasure();
            }
        }

        private void UnloadRow()
        {
            if (this.Row != null)
            {
                this.Row.Errors.CollectionChanged -= new NotifyCollectionChangedEventHandler(this.OnErrorsCollectionChanged);
            }
        }

        public void UpdateCurrentCell()
        {
            if (this._headerPresenter != null)
            {
                this._headerPresenter.UpdateCurrentCell();
            }
            if (this._presenter != null)
            {
                this._presenter.UpdateCurrentCell();
            }
        }

        internal void UpdateEditingRow()
        {
            if (this._headerPresenter != null)
            {
                this._headerPresenter.UpdateEditingRow();
            }
            if (this._presenter != null)
            {
                this._presenter.UpdateEditingRow();
            }
        }

        public void UpdateHeight(double newValue)
        {
            newValue = Math.Min(newValue, this.View.ScrollManager.AvailableSize.Height);
            if (this.Row.ActualDetailsVisibility == Visibility.Visible)
            {
                newValue -= this.DetailsRenderHeight;
                this.Row.Height = new DataGridLength((newValue > 0.0) ? newValue : 0.0);
            }
            else
            {
                this.Row.Height = new DataGridLength(newValue);
            }
        }

        internal void UpdateLines()
        {
            if (this._presenter != null)
            {
                this._presenter.UpdateLines();
            }
        }

        public void UpdateMouseOver()
        {
            if (!this.DataGrid.ShowFluidMouseOver)
            {
                this.Row.UpdateMouseOver();
                if (this._headerPresenter != null)
                {
                    this._headerPresenter.UpdateMouseOver();
                }
                if (this._presenter != null)
                {
                    this._presenter.UpdateMouseOver();
                }
            }
        }

        internal void UpdateRowAreMargin()
        {
            if (this._presenter != null)
            {
                this._presenter.RowAreaMargin = new Thickness(this.Row.Level * this.DataGrid.IndentWidth, 0.0, 0.0, 0.0);
            }
        }

        public void UpdateRowBackgroundAndForeground()
        {
            if (this._presenter != null)
            {
                DataGridRow row = this._presenter.Row;
                if ((row != null) && (row.Type == DataGridRowType.Item))
                {
                    if ((row.LocalIndex % 2) == 0)
                    {
                        this._presenter.SetValue(DataGridRowPresenter.BackgroundBrushProperty, this.DataGrid.RowBackground);
                        this._presenter.Foreground = this.DataGrid.RowForeground;
                    }
                    else
                    {
                        this._presenter.SetValue(DataGridRowPresenter.BackgroundBrushProperty, this.DataGrid.AlternatingRowBackground);
                        this._presenter.Foreground = this.DataGrid.AlternatingRowForeground;
                    }
                }
                else
                {
                    this._presenter.SetValue(DataGridRowPresenter.BackgroundBrushProperty, this.DataGrid.HeaderBackground);
                    this._presenter.ClearValue(Control.ForegroundProperty);
                }
                this._presenter.UpdateLines();
            }
        }

        public void UpdateRowDetailsBackgroundAndForeground()
        {
            if (this._detailsPresenter != null)
            {
                DataGridRow row = this._detailsPresenter.Row;
                if ((row != null) && (row.Type == DataGridRowType.Item))
                {
                    if ((row.LocalIndex % 2) == 0)
                    {
                        this._detailsPresenter.Background = this.DataGrid.RowBackground;
                        this._detailsPresenter.Foreground = this.DataGrid.RowForeground;
                    }
                    else
                    {
                        this._detailsPresenter.Background = this.DataGrid.AlternatingRowBackground;
                        this._detailsPresenter.Foreground = this.DataGrid.AlternatingRowForeground;
                    }
                }
                else
                {
                    this._detailsPresenter.SetBinding<DataGrid>(Control.BackgroundProperty, this.DataGrid, dg => dg.HeaderBackground);
                    this._detailsPresenter.SetBinding<DataGrid>(Control.ForegroundProperty, this.DataGrid, dg => dg.HeaderForeground);
                }
            }
        }

        public void UpdateSelection()
        {
            this.Row.UpdateSelection();
            if (this._headerPresenter != null)
            {
                this._headerPresenter.UpdateSelection();
            }
            if (this._presenter != null)
            {
                this._presenter.UpdateSelection();
            }
        }

        public void UpdateValidationState()
        {
            if (this._headerPresenter != null)
            {
                this._headerPresenter.UpdateValidationState();
            }
            if (this._presenter != null)
            {
                this._presenter.UpdateValidationState();
            }
        }

        // Properties
        public DataGrid DataGrid
        {
            get
            {
                return this.View.DataGrid;
            }
        }

        public double DesiredHeight
        {
            get
            {
                double? nullable = this._desiredHeight;
                if (!nullable.HasValue)
                {
                    return 0.0;
                }
                return nullable.GetValueOrDefault();
            }
            set
            {
                double num = Math.Max(this.MinHeight, Math.Min(this.MaxHeight, Math.Ceiling(value)));
                double? nullable = this._desiredHeight;
                double num2 = num;
                if ((nullable.GetValueOrDefault() != num2) || !nullable.HasValue)
                {
                    this._desiredHeight = new double?(num);
                    this.View.OnRowActualHeightChanged(this);
                }
            }
        }

        public bool DesiredHeightIsSet
        {
            get
            {
                return this._desiredHeight.HasValue;
            }
        }

        public double DetailsDesiredHeight
        {
            get
            {
                double? nullable = this._detailsDesiredHeight;
                if (!nullable.HasValue)
                {
                    return 0.0;
                }
                return nullable.GetValueOrDefault();
            }
            set
            {
                double? nullable = this._detailsDesiredHeight;
                double num = value;
                if ((nullable.GetValueOrDefault() != num) || !nullable.HasValue)
                {
                    this._detailsDesiredHeight = new double?(value);
                    this.View.OnRowActualHeightChanged(this);
                }
            }
        }

        public double DetailsMeasureHeight
        {
            get
            {
                return double.PositiveInfinity;
            }
        }

        public double DetailsRenderHeight
        {
            get
            {
                double? nullable = this._detailsDesiredHeight;
                if (!nullable.HasValue)
                {
                    return 0.0;
                }
                return nullable.GetValueOrDefault();
            }
        }

        public DataGridLength Height
        {
            get
            {
                return this.Row.GetHeight();
            }
        }

        public int Index
        {
            get
            {
                return this.Row.Index;
            }
        }

        public double MaxHeight
        {
            get
            {
                return this.Row.ActualMaxHeight;
            }
        }

        public int MaxHeightColumnDisplayIndex { get; set; }

        public double MeasureHeight
        {
            get
            {
                switch (this.Height.Type)
                {
                    case DataGridUnitType.Pixel:
                        return Math.Max(this.MinHeight, Math.Min(this.MaxHeight, this.Height.Value));
                }
                return this.MaxHeight;
            }
        }

        public double MinHeight
        {
            get
            {
                return this.Row.ActualMinHeight;
            }
        }

        public double Offset
        {
            get
            {
                return this._offset;
            }
            set
            {
                if (this._offset != value)
                {
                    this._offset = value;
                    if (this.View.RowsHeaderPanel != null)
                    {
                        this.View.RowsHeaderPanel.InvalidateMeasure();
                    }
                }
            }
        }

        public RecyclingPanel Panel
        {
            get
            {
                return this.View.RowsPanel;
            }
        }

        public double RenderHeight
        {
            get
            {
                switch (this.Height.Type)
                {
                    case DataGridUnitType.Pixel:
                        return this.MeasureHeight;
                }
                return this.DesiredHeight;
            }
        }

        public DataGridRow Row { get; private set; }

        public DataGridView View { get; private set; }
    }
}
